package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.mapper.settlement.CouponReportDataMapper;
import com.tiancheng.trade.settlement.model.settlement.CouponReportData;
import com.tiancheng.trade.settlement.service.settlement.ICouponsReportService;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import com.tiancheng.trade.settlement.util.JacksonJsonUtil;
import com.tiancheng.trade.settlement.util.ObjectConvertUtil;
import com.tiancheng.trade.settlement.vo.settlement.admin.CouponsReportResultVO;
import com.tiancheng.trade.settlement.vo.settlement.admin.CouponsReportVO;
import com.tiancheng.trade.settlement.vo.settlement.export.CouponsExportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class CouponsReportService implements ICouponsReportService {

    @Autowired
    private CouponReportDataMapper mapper;
    private final String format = "yyyy-MM-dd";
    @Autowired
    private ObjectMapper objectMapper;
    @Resource
    private JacksonJsonUtil jacksonJsonUtil;

    @Override
    public Map<String, Object> query(CouponsReportVO vo) {
        try {
            Map<String, Object> dataMap = new HashMap<>();
            //查询不到优惠券报表数据时，去统计一次并保存
            List<CouponReportData> datas = queryCouponReportDataList(vo);
            if (datas.isEmpty()) {
                List<CouponsReportResultVO> coupons = mapper.query(vo);
                if (coupons == null || coupons.isEmpty()) {
                    return dataMap;
                }
                for (CouponsReportResultVO resVo : coupons) {
                    CouponReportData data = new CouponReportData();
                    setCouponReportData(data, vo, resVo);
                    datas.add(data);
                }
                mapper.saveBatch(datas);
            }
            setDataMapRtn(datas, dataMap);
            return dataMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private List<CouponsReportResultVO> toCouponsReportResultVO(List<CouponReportData> couponReportDatas) {
        List<CouponsReportResultVO> couponsReportResults = new ArrayList<CouponsReportResultVO>();
        for (CouponReportData data : couponReportDatas) {
            CouponsReportResultVO vo = ObjectConvertUtil.convert(data, CouponsReportResultVO.class).get();
            vo.setOrderSourceCn(OrderSourceEnum.getDesc(vo.getOrderSource()));
            couponsReportResults.add(vo);
        }
        return couponsReportResults;
    }

    private List<CouponReportData> queryCouponReportDataList(CouponsReportVO vo) {
        QueryWrapper<CouponReportData> conditions = new QueryWrapper<>();
        if (StringUtils.isNotBlank(vo.getYearMonth())) {
            conditions.eq("statistics_time", vo.getYearMonth());
            conditions.orderByAsc("order_source");
            return mapper.selectList(conditions);
        }
        return new ArrayList<>();
    }

    @Override
    public Map<String, Object> update(CouponsReportVO vo) {
        Map<String, Object> dataMap = new HashMap<>();
        List<CouponReportData> datas = new ArrayList<>();
        for (OrderSourceEnum sourceEnum : OrderSourceEnum.values()) {
            QueryWrapper<CouponReportData> conditions = new QueryWrapper<>();
            conditions.eq("statistics_time", vo.getYearMonth());
            conditions.eq("order_source", sourceEnum.getCode());
            CouponReportData data = mapper.selectOne(conditions);
            vo.setOrderSource(sourceEnum.getCode());
            List<CouponsReportResultVO> coupons = mapper.query(vo);
            CouponsReportResultVO resVo = new CouponsReportResultVO();
            if (CollectionUtils.isNotEmpty(coupons)) {
                resVo = coupons.get(0);
            } else {
                resVo.setOrderSource(sourceEnum.getCode());
                resVo.setOrderSourceCn(sourceEnum.getDesc());
                resVo.setAmount("0");
            }
            if (data == null) {
                data = new CouponReportData();
                setCouponReportData(data, vo, resVo);
                datas.add(data);
            } else {
                setCouponReportData(data, vo, resVo);
                mapper.update(data);
            }
        }
        if (!datas.isEmpty()) {
            mapper.saveBatch(datas);
        }
        List<CouponReportData> rReportDatas = this.queryCouponReportDataList(vo);
        setDataMapRtn(rReportDatas, dataMap);
        return dataMap;
    }

    private void setDataMapRtn(List<CouponReportData> datas, Map<String, Object> dataMap) {
        if (!datas.isEmpty()) {
            List<CouponsReportResultVO> couponsReportResults = toCouponsReportResultVO(datas);
            dataMap.put("dataList", couponsReportResults);
            dataMap.put("statisticsTime", datas.get(0).getStatisticsTime());
            dataMap.put("generationTime", datas.get(0).getGenerationTime());
        }
    }

    private void setCouponReportData(CouponReportData data, CouponsReportVO vo, CouponsReportResultVO resVo) {
        data.setAmount(resVo.getAmount());
        data.setOrderSource(resVo.getOrderSource());
        data.setGenerationTime(DateTimeUtil.getSystemDate(format));
        data.setStatisticsTime(vo.getYearMonth());
    }

    @Override
    public void export(String yearMonth, HttpServletRequest request, HttpServletResponse response) {
        CouponsReportVO vo = new CouponsReportVO();
        vo.setYearMonth(yearMonth);
        List<CouponReportData> datas = queryCouponReportDataList(vo);
        List<CouponsExportVO> exports = null;
        try {
            exports = objectMapper.readValue(jacksonJsonUtil.toJson(datas), new TypeReference<List<CouponsExportVO>>() {
            });
        } catch (JsonMappingException e1) {
            e1.printStackTrace();
        } catch (JsonProcessingException e1) {
            e1.printStackTrace();
        }
        BigDecimal num = new BigDecimal("100");
        if (CollectionUtils.isNotEmpty(exports)) {
            exports.stream().forEach(billResult -> {
                if (StringUtils.isNotEmpty(billResult.getAmount())) {
                    BigDecimal amount = new BigDecimal(billResult.getAmount());
                    billResult.setAmount(amount.divide(num).toString());
                }
                billResult.setOrderSource(OrderSourceEnum.getDesc(billResult.getOrderSource()));
            });
        }
        List<Map<String, Object>> mapList = listConvert(exports);
        String date = DateTimeUtil.getSystemDate("yyyy-MM-dd");
        String fileName = "优惠券报表" + date + ".xlsx";
        String[] title = {"场景", "优惠金额"};
        Workbook workbook;
        try {
            workbook = ExcelUtil.buildWorkbook(fileName, title, mapList);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        } catch (IOException e) {
            log.info("导出差额明细数据出现异常{}", e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> listConvert(List<CouponsExportVO> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (CouponsExportVO t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
